/*
 * Copyright (c) 2011, TUgether, TU Braunschweig
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 /**
 * @author Mohamed Karray <mohamed.karray@gmx.de>
 *         Mark Stein <mark.stein.ms@gmail.com>
 *
 */


package de.tu_bs.tugether.liferayunit.liferayPages;

import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.text.*;
import java.util.*;

import org.apache.log4j.*;

import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.*;

import de.tu_bs.tugether.liferayunit.exceptions.*;
import de.tu_bs.tugether.liferayunit.liferayElements.*;
import de.tu_bs.tugether.liferayunit.liferayElements.portlets.*;
import de.tu_bs.tugether.liferayunit.util.*;

public class LiferayPage {

	final WebClient webClient;
	HtmlPage htmlPage;
	private Properties properties;
	List<Portlet> portletList;
	List<Tab> tabList;

	protected HtmlElement navigation;
	protected HtmlAnchor goToPublicPagelink;
	protected HtmlAnchor goToPrivatePagelink;
	protected HtmlElement docBar;
	private Map<String, ChatWindow> chatWindowList;

	protected Logger logger = Logger.getLogger(this.getClass());

	protected static final String XPATH_KEY_PORTLET = "portlet";
	protected static final String XPATH_KEY_IS_IN_LIFERAY_PORTAL = "isInLiferayPortal";
	protected static final String XPATH_KEY_IS_IN_PUBLIC_PAGE = "isInPublicPage";
	protected static final String XPATH_KEY_IS_IN_PRIVATE_PAGE = "isInPrivatePage";
	protected static final String XPATH_KEY_TAB_NAVIGATION = "navigation";
	protected static final String XPATH_KEY_ADD_TAB_LINK = "addTabLink";
	protected final static String XPATH_KEY_PUBLIC_PAGE_LINK = "goToPublicPageLink";
	protected final static String XPATH_KEY_PRIVATE_PAGE_LINK = "goToPrivatePageLink";
	protected static final String XPATH_KEY_DOCBAR = "docbar";
	protected static final String XPATH_KEY_ADD_PORTLET_WINDOW_CLOSE_BUTTON = "addPortlet.window.closeButton";
	protected static final String XPATH_KEY_ADD_PORTLET_WINDOW = "addPortlet.window";
	protected static final String XPATH_KEY_ADD_PORTLET_LINK = "addPortletLink";
	protected static final String XPATH_KEY_ADD_PORTLET_CATEGORY_LIST = "addPortlet.window.categoryList";
	protected static final String XPATH_KEY_ADD_PORTLET_ITEM_LIST = "addPortlet.window.category.portletItemList";
	protected static final String XPATH_KEY_CHAT_TAB = "chat-tab";
	protected static final String XPATH_KEY_CHAT_TAB_USERNAME = "chat-tab.username";
	protected static final String XPATH_KEY_ONLINE_USERS = "online-users";
	protected static final String XPATH_KEY_CHAT_WINDOW = "chat-window";
	protected static final String XPATH_KEY_SIGNED_IN_USER = "signed-in-user-name";
	protected static final String XPATH_KEY_SIGNED_OUT_LINK = "sign-out-link";
	protected static final String XPATH_KEY_GET_ONLINE_USER = "get-online-user";
	protected static final String XPATH_KEY_MANAGE_LOADER = "manage-span";
	protected static final String XPATH_KEY_MANAGE_PAGE = "manage-page-anchor";
	protected static final String XPATH_KEY_MANAGE_PAGE_CHILDREN = "manage-page-children-anchor";
	private static final String XPATH_KEY_MANAGE_ORDER_OF_CHILDREN = "manage-order-of-children-anchor";
	private static final String XPATH_KEY_UPDATE_ORDER_OF_CHILDREN = "update-order-of-children-button";
	protected static final String XPATH_KEY_INPUT_CHILD_PAGE_NAME = "input-child-page-name";
	protected static final String XPATH_KEY_CHILD_PAGE_SELECTION = "child-page-selection";
	protected static final String XPATH_KEY_DELETE_CHILD_PAGE_ICON = "delete-child-page-anchor";
	protected static final String XPATH_KEY_INPUT_CHILD_PAGE_SAVE = "savebutton-child-page";
	protected static final String XPATH_KEY_INPUT_MANAGE_PERMISSION = "input-manage-permission-button";
	private static final String XPATH_KEY_INPUT_SEARCH_PERMISSION = "input-search-permission";
	private static final String XPATH_KEY_BUTTON_SEARCH_PERMISSION = "button-search-permission";
	private static final String XPATH_KEY_PERMISSION_CHECKBOX = "permission-checkbox";
	private static final String XPATH_KEY_SAVE_BUTTON = "savebutton";
	private static final String XPATH_KEY_PERMISSION_FORM = "permission-form";


	enum XpathKeys {
		GET_TAB_WITH_NAME,
		REMOVE_PORTLET_ANCHOR;
	}


	public LiferayPage(URL url) throws Exception {
		this(url, null, null, -1);
	}

	public LiferayPage(final HtmlPage htmlPage) throws Exception {
		this.webClient = htmlPage.getWebClient();
		this.htmlPage = htmlPage;
		this.properties = new Properties();

		InputStream propertyFile = LiferayUtil.getProprtyFile(this.getClass().getSimpleName() + ".properties");
		this.properties.load(propertyFile);
		this.properties = this.addImportedProperties(properties);
//		logger = Logger.getLogger(this.getClass());
//		logger.addAppender(LiferayUtil.appender);
		logger.debug("Erzeuge: " + this.getClass().getSimpleName() + " mit dem URL: " + htmlPage.getUrl().toString());
		webClient.setThrowExceptionOnScriptError(true);
		initialize();
	}

	public LiferayPage(final URL url, BrowserVersion browserVersion, String proxyHost, int port) throws Exception {
		if (browserVersion != null) {
	        this.webClient = new WebClient(browserVersion);
        } else {
	        this.webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
        }
		ProxyConfig pc = new ProxyConfig();
		if (proxyHost != null) {
	        pc.setProxyHost(proxyHost);
        }
		if (port != -1) {
	        pc.setProxyPort(port);
        }
		this.htmlPage = webClient.getPage(url);
		this.properties = new Properties();
		InputStream propertyFile = LiferayUtil.getProprtyFile(this.getClass().getSimpleName() + ".properties");
		this.properties.load(propertyFile);
		this.properties = this.addImportedProperties(properties);
		logger = Logger.getLogger(this.getClass());
		logger.addAppender(LiferayUtil.appender);
		logger.debug("Erzeuge: " + this.getClass().getSimpleName() + " mit dem URL: " + url.getPath());
		webClient.setThrowExceptionOnScriptError(true);
		initialize();
	}

	public String getSignedInUserName() throws LiferayUnitException {
		HtmlElement el = this.getFirstByXPathKey(XPATH_KEY_SIGNED_IN_USER);
		return el.getTextContent();
	}

	public void signOut() throws LiferayElementNotFoundException, LiferayPropertyKeyNotFoundException, IOException {
		HtmlAnchor singnOutLink = this.<HtmlAnchor> getFirstByXPathKey(XPATH_KEY_SIGNED_OUT_LINK);
		singnOutLink.click();
	}

	public boolean isSignedIn() {
		HtmlBody body = (HtmlBody) this.getHtmlPage().getBody();
		String classAtr = body.getAttribute("class");
		return classAtr.contains("signed-in");
	}

	public void refresh() throws Exception {
		this.htmlPage = (HtmlPage) this.htmlPage.refresh();
		this.initialize();
	}

	public Tab addTab(String tabName) throws IOException, InterruptedException, LiferayUnitException {
		this.mouseMove();

		HtmlAnchor a = this.<HtmlAnchor> getFirstByXPathKey(XPATH_KEY_ADD_TAB_LINK);
		a.click();
		webClient.waitForBackgroundJavaScript(2000);
		for (int i = 0; i < 200; i++) {
			int s = htmlPage.getElementById("navigation").getElementsByTagName("input").size();
			if (s != 0) {
				HtmlTextInput ti = (HtmlTextInput) (htmlPage.getElementById("navigation").getElementsByTagName("input")
						.get(0));
				ti.setValueAttribute(tabName);
				HtmlButton button = (HtmlButton) (htmlPage.getElementById("navigation").getElementById("save"));
				button.click();
				initializeTabList();
				return tabList.get(tabList.size() - 1);
			}
			synchronized (htmlPage) {
				htmlPage.wait(500);
			}
		}
		return null;
	}

	public void goToPublicPage() throws Exception {
		HtmlPage page = this.goToPublicPagelink.click();
		this.htmlPage = page;
		this.initialize();
	}

	public void goToPrivatePage() throws Exception {
		HtmlPage page = this.goToPrivatePagelink.click();
		this.htmlPage = page;
		this.initialize();
	}

	/**
	 * addImportedProperties ist eine rekursive Methode beginne die Zuweisung
	 * aller schl�ssels der importet properties von der tifste ebene bis zum
	 * aktuelle propertie datei um die eintr�ge mit gleichem schl�ssel mit der
	 * aktuellsten schl�ssel zu �berschreiben
	 *
	 * @param prop
	 * @throws IOException
	 */
	private Properties addImportedProperties(Properties prop) throws IOException {
		Properties result = new Properties();
		String importFile = prop.getProperty("import");
		if (importFile != null) {
			Properties importetdProperties = new Properties();
			InputStream propertyFile = LiferayUtil.getProprtyFile(importFile);
			importetdProperties.load(propertyFile);
			result.putAll(this.addImportedProperties(importetdProperties));
		}
		result.putAll(prop);
		return result;
	}

	public void initializePortletList() throws Exception {
		this.portletList = new LinkedList<Portlet>();
		Properties specialPortletClasses = new Properties();
		InputStream is = LiferayUtil.getProprtyFile("Portlets.properties");
		specialPortletClasses.load(is);
		String portletXPath = specialPortletClasses.getProperty(XPATH_KEY_PORTLET);
		specialPortletClasses.remove(XPATH_KEY_PORTLET);
		List<HtmlElement> portletHtmlElementList = (List<HtmlElement>) this.htmlPage.getByXPath(portletXPath);
		String foundPortlets = "";
		for (HtmlElement el : portletHtmlElementList) {

			String specificPortletClassName = getSpecificPortletClassName(specialPortletClasses, el);
			if (specificPortletClassName == null) {
				Portlet portlet = new Portlet(el, this);
				foundPortlets += "Portlet: '" + portlet.getTitle() + "'\n ";
				this.portletList.add(portlet);
			} else {
				Portlet specialPortletObj = createPortletObject(el, specificPortletClassName);
				foundPortlets += " " + specialPortletObj.getClass().getSimpleName() + ": '"
						+ specialPortletObj.getTitle() + "'\n ";
				this.portletList.add(specialPortletObj);
			}
		}
		logger.debug("Identifizierte Portlets: [" + foundPortlets + "]");

	}

	private String getSpecificPortletClassName(Properties specialPortletClasses, HtmlElement el) {
		for (Object key : specialPortletClasses.keySet()) {
			String specialPortletXPath = specialPortletClasses.getProperty((String) key);
			HtmlElement searchedElement = el.getFirstByXPath(specialPortletXPath);
			if (searchedElement != null) {
				return key.toString();
			}
		}
		return null;
	}

	private Portlet createPortletObject(HtmlElement el, String portletClassName) throws ClassNotFoundException,
			NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
		Class portletClass = Class.forName(portletClassName);
		Constructor specialPortletConstructor = portletClass.getConstructor(HtmlElement.class, LiferayPage.class);
		return (Portlet) specialPortletConstructor.newInstance(el, this);
	}

	public <T extends Portlet> T getPortletByTitle(String portletTitle) throws Exception {
		for (Object el : this.portletList) {
			if (((Portlet) el).getTitle().equalsIgnoreCase(portletTitle)) {
				return (T) el;
			}
		}
		return null;
	}

	public <T extends Portlet> T getPortletById(String id) {
		for (Object el : this.portletList) {
			if (((Portlet) el).getId().equalsIgnoreCase(id)) {
				return (T) el;
			}
		}
		return null;
	}

	public void mouseMove() {
		for (HtmlElement el : this.htmlPage.getAllHtmlChildElements()) {
			el.mouseMove();
			el.mouseOver();
		}
	}

	public void setPage(HtmlPage page) {
		this.htmlPage = page;
	}

	public boolean addPortletByTitle(String title) throws Exception {
		String log = "Einf�gen des Portlets: '" + title + "': ";
		HtmlElement addPortletLink = this.getFirstByXPathKey(XPATH_KEY_ADD_PORTLET_LINK);
		this.mouseMove();
		addPortletLink.click();
		Thread.sleep(5000);
		for (Object obj1 : htmlPage.getByXPath(getXPath(XPATH_KEY_ADD_PORTLET_ITEM_LIST))) {
			HtmlElement portlet_item = (HtmlElement) obj1;
			HtmlElement title_el = portlet_item.getElementsByTagName("p").get(0);
			HtmlElement add_link = portlet_item.getElementsByTagName("a").get(0);
			if (!add_link.isDisplayed()) {
				if (title.equalsIgnoreCase(title_el.asText())) {
					logger.error(log + "Der Link zum Hinzufügen ist nicht sichtbar");
//					return false;
				}
				break;
			}
			String substringTitle = title_el.asText().substring(0, title_el.asText().indexOf(add_link.asText()) - 1);
			if (title.equalsIgnoreCase(substringTitle)) {
				add_link.click();
				HtmlElement closeWin = this.getFirstByXPathKey(XPATH_KEY_ADD_PORTLET_WINDOW_CLOSE_BUTTON);
				closeWin.click();
				webClient.waitForBackgroundJavaScript(3000);
				this.initializePortletList();
				if (this.getPortletByTitle(title) != null) {
					logger.debug(log + "mit Erfolg");
					return true;
				}
				logger.error(log + "Link zum Hinzufügen geklickt aber Portlet nicht eingefügt!");
				return false;
			}
		}
		logger.error(log + "Portlet wurde nicht gefunden");
		return false;
	}

	public boolean isFriendOnline(String username) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException {
		return getOnlineUser(username) != null;
	}

	private HtmlElement getOnlineUser(String username) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException {
		try {
			HtmlElement onlineUser = this.getFirstByXPathKey(XPATH_KEY_GET_ONLINE_USER, username);
			return onlineUser;
		} catch (LiferayElementNotFoundException e) {
			return null;
		}
	}

	public ChatMessage getLastOutgoingMessage(String friendUsername) throws Exception {
		HtmlElement onlineUser_Element = getOnlineUser(friendUsername);
		if (onlineUser_Element == null) {
			return null;
		}
		onlineUser_Element.click();
		this.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000);
		ChatWindow chatWindow = getChatWindow(friendUsername);
		return chatWindow.getLastOutgoingMessage();
	}

	public ChatMessage getLastIncommingMessage(String friendUsername) throws Exception {
		HtmlElement onlineUser_Element = getOnlineUser(friendUsername);
		if (onlineUser_Element == null) {
			return null;
		}
		onlineUser_Element.click();
		this.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000);
		ChatWindow chatWindow = getChatWindow(friendUsername);
		return chatWindow.getLastIncommingMessage();
	}

	public void sendChatMessage(String friendUsername, String message) throws Exception {
		logger.debug("Beginne Chat Nachricht '" + message + "' an '" + friendUsername + "' senden");
		HtmlElement onlineUser_Element = getOnlineUser(friendUsername);
		if (onlineUser_Element == null) {
			logger.error("der Freund '" + friendUsername + "' ist incht online");
			return;

		}
		onlineUser_Element.click();
		this.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000);
		ChatWindow chatWindow = getChatWindow(friendUsername);
		chatWindow.send(message);
		logger.debug("Chat Nachricht '" + message + "' an '" + friendUsername + "' gesendet");
	}

	private ChatWindow getChatWindow(String username) throws Exception {
		HtmlElement result = this.getFirstByXPathKey(XPATH_KEY_CHAT_WINDOW, username);
		System.out.println(result.asText());
		return new ChatWindow(result, this);
	}

	public void initialize() throws Exception {
		webClient.setThrowExceptionOnScriptError(true);
		webClient.setAjaxController(new NicelyResynchronizingAjaxController());
		try {
			this.navigation = this.getFirstByXPathKey(XPATH_KEY_TAB_NAVIGATION);
		} catch (LiferayElementNotFoundException e) {
			this.navigation = null;
		}
		try {
			this.docBar = this.getFirstByXPathKey(XPATH_KEY_DOCBAR);
		} catch (LiferayElementNotFoundException e) {
			this.docBar = null;
		}
		try {
			this.goToPrivatePagelink = this.<HtmlAnchor> getFirstByXPathKey(XPATH_KEY_PRIVATE_PAGE_LINK);

		} catch (LiferayElementNotFoundException e) {
			this.goToPrivatePagelink = null;
		}
		try {
			this.goToPublicPagelink = this.<HtmlAnchor> getFirstByXPathKey(XPATH_KEY_PUBLIC_PAGE_LINK);
		} catch (LiferayElementNotFoundException e) {
			this.goToPublicPagelink = null;
		}
		initializePortletList();
		initializeTabList();
	}

	public void initializeTabList() throws LiferayElementNotFoundException, IOException {
		this.tabList = new LinkedList<Tab>();

		HtmlElement ul = this.navigation.getElementsByTagName("ul").get(0);
		for (HtmlElement el : ul.getElementsByTagName("li")) {
			Tab tab = new Tab((HtmlListItem) el, this);
			this.tabList.add(tab);
		}
	}

	public void initialize(HtmlPage page) throws Exception {
		this.htmlPage = page;
		this.initialize();
	}

	public WebClient getWebClient() {
		return webClient;
	}

	public HtmlPage getHtmlPage() {
		return htmlPage;
	}

	public Properties getProperties() {
		return properties;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	protected String getXPath(String key, String... objects) {
		String p = properties.getProperty(key);
		if (objects.length == 0) {
	        return p;
        }
		return MessageFormat.format(p, objects);
	}

	protected List<?> getByXPathKey(String key, String... objects) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException {
		String xPath = getXPath(key, objects);
		if (xPath == null) {
			throw new LiferayPropertyKeyNotFoundException("key: '" + key + "' not found in the Properties file: '"
					+ this.getClass().getSimpleName() + ".properties'");
		} else {
			List<?> result = this.htmlPage.getByXPath(xPath);
			if (result == null) {
	            throw new LiferayElementNotFoundException("Das gesuchte HTML-Element mit dem Key: '"+key+"' wurde nicht gefunden");
            } else {
				return result;
			}
		}
	}

	private HtmlAnchor getFirstByXPathKey(XpathKeys xpath, String[] values) throws Exception {
		return getFirstByXPathKey(xpath.name(), values);
	}

	protected <T extends HtmlElement> T getFirstByXPathKey(String key, String... objects)
			throws LiferayPropertyKeyNotFoundException, LiferayElementNotFoundException {
		String xPath = getXPath(key, objects);
		if (xPath == null) {
			throw new LiferayPropertyKeyNotFoundException("key: '" + key + "' not found in the Properties file: '"
					+ this.getClass().getSimpleName() + ".properties'");
		} else {
			Object element = this.htmlPage.getFirstByXPath(xPath);
			if (element == null) {
	            throw new LiferayElementNotFoundException("Das gesuchte HTML-Element mit dem Key: '"+key+"' wurde nicht gefunden");
            } else {
				return (T) element;
			}
		}
	}

	protected boolean findElementWithXPathKey(String key) {
		try {
			this.getFirstByXPathKey(key);
			return true;
		} catch (LiferayElementNotFoundException e) {
			return false;
		} catch (LiferayPropertyKeyNotFoundException e) {
			e.printStackTrace();
			return false;
		}
	}

	public boolean isInLiferayPortal() {
		return this.findElementWithXPathKey(XPATH_KEY_IS_IN_LIFERAY_PORTAL);
	}

	public boolean isInPublicPage() {
		return this.findElementWithXPathKey(XPATH_KEY_IS_IN_PUBLIC_PAGE);
	}

	public boolean isInPrivatePage() {
		return this.findElementWithXPathKey(XPATH_KEY_IS_IN_PRIVATE_PAGE);
	}

	@Override
	public String toString() {
		return "Page of type: " + this.getClass() + " \n it represent the html Page: " + htmlPage.toString() + "\n"
				+ htmlPage.asText();

	}

	public void signOutAndClose() throws LiferayElementNotFoundException, LiferayPropertyKeyNotFoundException,
			IOException {
		this.signOut();
		this.close();
	}

	public void close() {
		this.webClient.closeAllWindows();

	}

	public void waitUntilFriendIsOffline(String username) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException, InterruptedException {
		do {
			this.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000);
			synchronized (this.htmlPage) {
				this.htmlPage.wait(500);
			}
		} while (this.isFriendOnline(username));
	}

	public void waitUntilFriendIsOnline(String username) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException, InterruptedException {
		do {
			this.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000);
			synchronized (this.htmlPage) {
				this.htmlPage.wait(500);
			}
		} while (!this.isFriendOnline(username));
	}

	public boolean isTabSelected(String tabName) throws LiferayElementNotFoundException, LiferayPropertyKeyNotFoundException{
		return getSelectedTab().getTabName().equals(tabName);
	}

	public Tab getSelectedTab() throws LiferayElementNotFoundException, LiferayPropertyKeyNotFoundException {
		for (Tab tab : this.tabList) {
			if (tab.isSelected()) {
				return tab;
			}
		}
		return null;

	}

	public Tab getTab(String tabName) throws Exception {
		try {
			for (Tab tab : this.tabList) {
				if (tab.getTabName().equals(tabName)) {
					return tab;
				}
			}
		} catch (LiferayElementNotFoundException e) {
			logger.debug("getTab schlug beim ersten mal fehl, starte zweiten (letzten) Versuch");
			this.initialize();
			for (Tab tab : this.tabList) {
				if (tab.getTabName().equals(tabName)) {
					return tab;
				}
			}
		}
		return null;
	}

	public void renameTab(String tabName, String newTabName) throws Exception {
		Tab tab = this.getTab(tabName);
		tab.rename(newTabName);
	}
	public void goToTab(String tabName) throws Exception {
	  logger.debug("go to tab " + tabName);
		Tab tab = this.getTab(tabName);
		tab.getHtmlElement().mouseMove();
		HtmlPage page = tab.click();
		this.setPage(page);
		this.initialize();
	}

	public void deleteTab(String tabName) throws Exception {
		Tab tab = this.getTab(tabName);
		tab.delete();
	}

	public List<Tab> getTabs() {
		return tabList;
	}

	public void logout() throws LiferayPropertyKeyNotFoundException, LiferayElementNotFoundException, IOException {
		signOut();
	}

	public void addSubTab(String title) throws Exception {
		logger.debug("add subtab: '" + title + "': ");
		HtmlPage page = getManagePage();

		HtmlElement childrenLink = page.getFirstByXPath(getXPath(XPATH_KEY_MANAGE_PAGE_CHILDREN));
		page = childrenLink.click();

//		webClient.waitForBackgroundJavaScript(3000);

		HtmlTextInput input = page.getFirstByXPath(getXPath(XPATH_KEY_INPUT_CHILD_PAGE_NAME));
		HtmlSubmitInput save = page.getFirstByXPath(getXPath(XPATH_KEY_INPUT_CHILD_PAGE_SAVE));
		input.setValueAttribute(title);
		try{
			save.click();
		} catch(NullPointerException e){
		}

		goToStartPage();
		initialize();
	}

	public void deleteSubTab(String title) throws Exception {
		logger.debug("delete subtab: '" + title + "': ");
		HtmlPage page = getManagePage();

		HtmlElement childrenLink = page.getFirstByXPath(getXPath(XPATH_KEY_MANAGE_PAGE_CHILDREN));
		page = childrenLink.click();

		webClient.waitForBackgroundJavaScript(3000);

		HtmlElement childrenOrderLink = page.getFirstByXPath(getXPath(XPATH_KEY_MANAGE_ORDER_OF_CHILDREN));
		page = childrenOrderLink.click();

		webClient.waitForBackgroundJavaScript(3000);

		HtmlElement subTabSelectElement =  page.getFirstByXPath(getXPath(XPATH_KEY_CHILD_PAGE_SELECTION, title));
		subTabSelectElement.click();

		HtmlElement removeIcon =  page.getFirstByXPath(getXPath(XPATH_KEY_DELETE_CHILD_PAGE_ICON));
		removeIcon.click();


		HtmlButtonInput update = page.getFirstByXPath(getXPath(XPATH_KEY_UPDATE_ORDER_OF_CHILDREN));
		try{
			update.click();
		} catch(NullPointerException e){
		}
	}


	public void removeAllAuthorization(String role) throws Exception {
		logger.debug("LiferayPage.removeAllAuthorization(...) role: " + role);
		HtmlPage page = goToPermissionsPage(role);

		for (PermissionType pType : PermissionType.values()) {
			HtmlCheckBoxInput check = page.getFirstByXPath(getXPath(XPATH_KEY_PERMISSION_CHECKBOX, pType.name()));
			if (check.isChecked()) {
				check.click();
			}
		}

		HtmlSubmitInput save = page.getFirstByXPath(getXPath(XPATH_KEY_SAVE_BUTTON));
		try {
			save.click();
		} catch (NullPointerException e) {
		}

	}

	private HtmlPage goToPermissionsPage(String permission) throws LiferayPropertyKeyNotFoundException, LiferayElementNotFoundException,
			IOException {
		logger.debug("go to permissions page and search for permission [" + permission + "]");
		HtmlPage page = getManagePage();

		HtmlButtonInput permissionsButton = page.getFirstByXPath(getXPath(XPATH_KEY_INPUT_MANAGE_PERMISSION));
		page = permissionsButton.click();

		webClient.waitForBackgroundJavaScript(3000);

		HtmlForm form = page.getFirstByXPath(getXPath(XPATH_KEY_PERMISSION_FORM));
		HtmlTextInput input = form.getFirstByXPath(getXPath(XPATH_KEY_INPUT_SEARCH_PERMISSION));
		HtmlSubmitInput search = form.getFirstByXPath(getXPath(XPATH_KEY_BUTTON_SEARCH_PERMISSION));
		input.setValueAttribute(permission);
		page.getWebClient().setJavaScriptEnabled(false);
		page = search.click();
		page.getWebClient().setJavaScriptEnabled(true);
		return page;
	}

	private HtmlPage getManagePage() throws LiferayPropertyKeyNotFoundException, LiferayElementNotFoundException, IOException {
		HtmlElement manageLoader = this.getFirstByXPathKey(XPATH_KEY_MANAGE_LOADER);
		manageLoader.mouseMove();
		manageLoader.mouseOver();
//		webClient.waitForBackgroundJavaScript(3000);

		HtmlElement managePageLink = this.getFirstByXPathKey(XPATH_KEY_MANAGE_PAGE);
		HtmlPage page = managePageLink.click();

//		webClient.waitForBackgroundJavaScript(3000);
		return page;
	}

	public void goToStartPage() throws Exception {
		goToTab("Welcome");
	}

	public void goToSubTab(String subpage) throws Exception {
		HtmlPage page = clickElement(XpathKeys.GET_TAB_WITH_NAME, subpage);
		this.setPage(page);
		this.initialize();
	}

	public void removePortlet(String internalPortletId) throws Exception {
		logger.debug("remove portlet: " +  internalPortletId);
		clickElement(XpathKeys.REMOVE_PORTLET_ANCHOR, "_" + internalPortletId);
	}

	private HtmlPage clickElement(XpathKeys xpath, String... values) throws Exception {
		HtmlAnchor link = this.getFirstByXPathKey(xpath, values);
		HtmlPage page = link.click();
		return page;
	}

}
